package com.cyys.modules.system.service.param;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cyys.common.ql.AR;
import com.cyys.common.services.CyysBaseService;
import com.cyys.common.utils.StringUtil;
import com.cyys.modules.core.sysParam.ParamRegionUtil;
import com.cyys.modules.system.dao.param.ParamRegionDao;
import com.cyys.modules.system.model.param.ParamRegion;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service("paramRegionService")
@Transactional(readOnly = true)
public class ParamRegionService extends CyysBaseService<ParamRegionDao,ParamRegion> {
	/**
	 * 新增或者修改的地域节点
	 * @param paramRegion
	 */
	@Transactional(readOnly = false)
	public AR save(ParamRegion paramRegion){
		if (StringUtil.isBlank(paramRegion.getId())) { // 新增
			ParamRegion region = this.getByCityCode(paramRegion.getCityCode());
			if(region != null){
				return AR.failed("该区域编码已经存在");
			}
			if(StringUtil.isNotBlank(paramRegion.getParentId())){
				ParamRegion parent = this.getById(paramRegion.getParentId());
				if(parent == null){
					return AR.failed("上一级区域不存在");
				}
				paramRegion.setLevel(parent.getLevel() + 1);
				// 修改父类的属性
				if(parent.getHasChild()!=1){
					parent.setHasChild(1); // 设置有子类
					dao.updateById(parent);
				}
			}else{
				paramRegion.setLevel(0);
			}
			paramRegion.setHasChild(0);
			dao.insert(paramRegion);
		} else { // 修改
			ParamRegion oldRegion = this.getById(paramRegion.getId());
			if(oldRegion==null){
				return AR.failed("当前编辑区域不存在");
			}
			if(StringUtil.isNotBlank(paramRegion.getCityCode())){
				ParamRegion region = this.getByCityCode(paramRegion.getCityCode());
				if(region != null && !region.getId().equals(paramRegion.getId())){
					return AR.failed("该区域编码已经存在");
				}
			}
			dao.updateById(paramRegion);
		}
		return AR.ok(paramRegion,"保存成功");
	}

	/**
	 * 根据parentId查询子列表
	 * @param parentId
	 * @return
	 * @throws Exception
	 */
	public List<ParamRegion> listByParentId(String parentId) throws Exception {
		return dao.getByParentId(parentId);
	}

	/**
	 * 查询树节点（用于前端树结构显示），注意：不是一次性查询所有树结构，是一开始加载一二级节点，后续点击再查询
	 * @param parentId
	 * @param isShowParent parentId不为空时是否显示parent
	 * @return
	 * @throws Exception
	 */
	public List<ParamRegion> listForTree(String parentId, boolean isShowParent) throws Exception {
		if (StringUtil.isBlank(parentId)) {//为空时查询第一、第二级数据，目前第一级别就一个节点，因此只需两个sql就可以查询出来
			List<ParamRegion> list = dao.getByParentId(null);
			for (ParamRegion paramRegion : list) {
				List<ParamRegion> childrenList = dao.getByParentId(paramRegion.getId());
				paramRegion.setChildren(childrenList);
				paramRegion.setOpen(true);
			}
			return list;
		} else {//不为空直接查询子节点
			if(isShowParent){
				List<ParamRegion> list= new ArrayList<>();
				ParamRegion parent= dao.selectById(parentId);
				parent.setOpen(true);
				parent.setChildren(dao.getByParentId(parentId));
				list.add(parent);
				return list;
			}else{
				return dao.getByParentId(parentId);
			}
		}
	}

	/**
	 * 查询所有地域节点
	 * isHaveTop0 是否包含0级节点
	 * @return
	 * @throws Exception
	 */
	public List<ParamRegion> listAllTree(boolean isHaveTop0) throws Exception {
		List<ParamRegion> topList = new ArrayList<>();
		QueryWrapper qw= new QueryWrapper<>();
		qw.orderByAsc("level,sort");
		List<ParamRegion> list= listAll(qw);
		if(list!=null && list.size()>0) {
			//按照parentId分组,存储所有parentId的子节点list
			Map<String, List<ParamRegion>> mapByParentId = list.stream().collect(Collectors.groupingBy(m ->{
				if(StringUtil.isBlank(m.getParentId()))
					return "TOP0";//第一层节点
				return m.getParentId();
			}, LinkedHashMap::new, Collectors.toList()));
			topList = mapByParentId.get("TOP0");//第一层
			setChlid(topList, mapByParentId);
		}
		if(!isHaveTop0){
			return topList.get(0).getChildren();//目前顶级节点只有一级:中华人民共和国
		}
		return topList;
	}

	/**
	 * 设置子节点
	 * @param list 需要设置子节点的循环列表
	 * @param mapByParentId key为parentId，value为parentId对应的子节点list
	 */
	public void setChlid(List<ParamRegion> list, Map<String, List<ParamRegion>> mapByParentId){
		if(list!=null && list.size()>0) {
			list.stream().forEach(obj -> {
				//obj的子节点
				List<ParamRegion> children= mapByParentId.get(obj.getId());
				obj.setChildren(children);
				setChlid(children, mapByParentId);
			});
		}
	}

	@Transactional(readOnly = false)
	public AR deleteById(String id){
		if (StringUtil.isBlank(id)) {
			return AR.failed("ID为空");
		}
		ParamRegion paramRegion = dao.selectById(id);
		int count = dao.chlidNum(id);
		if (count > 0) {
			return AR.failed("有子元素，不允许删除！");
		}
		dao.deleteById(id);
		// 修改父类属性
		if (StringUtil.isNotBlank(paramRegion.getParentId())) {
			int chlidNum = dao.chlidNum(paramRegion.getParentId());
			if (chlidNum == 0) {
				ParamRegion parent= new ParamRegion();
				parent.setId(paramRegion.getParentId());
				parent.setHasChild(0);
				dao.updateById(parent);
			}
		}
		return AR.ok("删除成功");
	}

	@Transactional(readOnly = false)
	public AR deleteBatchIds(String ids){
		if (StringUtil.isBlank(ids)) {
			return AR.failed("ID为空");
		}
		List idsInt = Arrays.asList(ids.split(","));
		List<ParamRegion> paramRegionList = dao.selectBatchIds(idsInt);

		/**
		 * 存储去重后的parentId列表，一般都是删除同一个父节点下的子节点，所以一般父节点就一个，去重后减少数据库操作次数
		 */
		List<String> parentIdList= new ArrayList<>();

		// 检查批量删除数据是否存在问题
		for (ParamRegion paramRegion : paramRegionList) {
			int count = dao.chlidNum(paramRegion.getId());
			if (count > 0) {
				return AR.failed(paramRegion.getName() + "有子元素，不允许删除！");
			}
			if(StringUtil.isNotBlank(paramRegion.getParentId())
					&& !parentIdList.contains(paramRegion.getParentId())){
				parentIdList.add(paramRegion.getParentId());
			}
		}
		dao.deleteBatchIds(idsInt);

		//更新父类的hasChild属性
		for (String parentId : parentIdList) {
			int chlidNum= dao.chlidNum(parentId);
			if(chlidNum==0){
				ParamRegion parent= new ParamRegion();
				parent.setId(parentId);
				parent.setHasChild(0);
				dao.updateById(parent);
			}
		}
		return AR.ok("删除成功");
	}

	/**
	 * 根据地域名称获取code
	 * @param regionName
	 * @return
	 * @throws Exception
	 */
	public String getByRegionName(String regionName) throws Exception {
		if(StringUtil.isBlank(regionName)){
			return "";
		}
		ParamRegion entity = new ParamRegion();
		entity.setName(regionName);
		QueryWrapper<ParamRegion> qw = new QueryWrapper<>();
		qw.setEntity(entity);
		try {   //可能会查询出多个地区
			return dao.selectOne(qw).getCityCode();
		}catch (Exception e){
			return "";
		}
	}

	/** 根据区域编码查询区域信息*/
	public ParamRegion getByCityCode(String cityCode) {
		return dao.getByCityCode(cityCode);
	}

	/**
	 * 根据地域ID获取地域名称(先从redis取，没有从数据库取)
	 * @param id
	 */
	public String getRegionNameById(String id){
		if(StringUtil.isNotBlank(id)){
			ParamRegion region= ParamRegionUtil.getParamRegionMap(id);
			if(region!=null){
				return region.getName();
			}
			region= dao.selectById(id);
			if(region!=null){
				return region.getName();
			}
		}
		return "";
	}
}
